/*
 * GenotypeMutator.cpp
 *
 *  Created on: 11-01-2011
 *      Author: Przemek
 */

#include "world/creation/GenotypeMutator.hpp"
#include "biology/Genotype.hpp"
#include "utils/Randomizer.hpp"
#include "utils/MathUtils.hpp"
#include "pch.hpp"
using namespace std;

GenotypeMutator::GenotypeMutator(const Genotype& first, const Genotype& second) :
	first(first), second(second)
{

}

Genotype GenotypeMutator::mutate() const
{
	float hungerIncAvg = (first.getHungerIncreasingSpeed() + second.getHungerIncreasingSpeed()) / 2;
	float libidoIncAvg = (first.getLibidoIncreasingSpeed() + second.getLibidoIncreasingSpeed()) / 2;
	float lifeIncAvg = (first.getLifeIncreasingSpeed() + second.getLifeIncreasingSpeed()) / 2;
	float angVelAvg = (first.getMaxAngularVelocityInDegreeses()
			+ second.getMaxAngularVelocityInDegreeses()) / 2;
	float movSpeedAvg = (first.getMaxMovementSpeed() + second.getMaxMovementSpeed()) / 2;
	float sightDistAvg = (first.getSightDistance() + second.getSightDistance()) / 2;
	float sightRangeAvg = (first.getSightRange() + second.getSightRange()) / 2;

	float hungerIncRange = fabs(first.getHungerIncreasingSpeed() - second.getHungerIncreasingSpeed());
	float libidoIncRange = fabs(first.getLibidoIncreasingSpeed() - second.getLibidoIncreasingSpeed());
	float lifeIncRange = fabs(first.getLifeIncreasingSpeed() - second.getLifeIncreasingSpeed());
	float angVelRange = max(1.0f, fabs(first.getMaxAngularVelocityInDegreeses()
			- second.getMaxAngularVelocityInDegreeses()));
	float movSpeedRange = fabs(first.getMaxMovementSpeed() - second.getMaxMovementSpeed());
	float sightDistRange = fabs(first.getSightDistance() - second.getSightDistance());
	float sightRangeRange = fabs(first.getSightRange() - second.getSightRange());

	float hungerInc = generateRandomValue(hungerIncAvg, hungerIncRange);
	float libidoInc = generateRandomValue(libidoIncAvg, libidoIncRange);
	float lifeInc = generateRandomValue(lifeIncAvg, lifeIncRange);
	float angVel = generateRandomValue(angVelAvg, angVelRange);
	float movSpeed = generateRandomValue(movSpeedAvg, movSpeedRange);
	float sightDist = generateRandomValue(sightDistAvg, sightDistRange);
	float sightRange = generateRandomValue(sightRangeAvg, sightRangeRange);

	return Genotype(first.isCarnivore(), hungerInc, libidoInc, lifeInc, angVel, movSpeed, sightDist,
			sightRange);
}

float GenotypeMutator::generateRandomValue(float averange, float range) const
{
	float randValue = Randomizer::nextUniformFloat();
	randValue *= 2;
	randValue *= randValue;
	if(Randomizer::nextInt(2) == 0)
	{
		randValue *= -1;
	}
	return MathUtils::trimValue(averange + (range / 2) * randValue, 0.0f, 4 * averange);
}
